﻿using WebApp.BLL.Base;
using WebApp.Common;
using WebApp.Common.Caching;
using WebApp.DAL;
using WebApp.Models;
using WebApp.ViewModels;
using WebApp.ViewModels.Manage;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WebApp.BLL;
using System.Web.Security;
using WebApp.BLL.Basic;
using System.Web.Mvc;

namespace WebApp.BLL.Manage
{
    public class S_userService : BaseService<S_user>
    {
        #region const


        #endregion

        #region DAL

        private S_user_roleRepository userRoleRepository = new S_user_roleRepository();
        //private P_study_siteuserRepository siteuserRepository = new P_study_siteuserRepository();

        #endregion

        #region 构造

        public S_userService() : base(new S_userRepository()) { }

        #endregion

        #region FindByUsername

        public S_user FindByUsername(string username)
        {
            return this.CurrentRepository.Find(p => p.Username == username && p.Isdeleted == "0");
        }

        public S_user FindByUname(string username)
        {
            return this.CurrentRepository.Entities.FirstOrDefault(p => p.Username == username && p.Isdeleted == "0");
        }
        #endregion

        #region Exist

        public bool Exist(int id, string username)
        {
            if (id == 0)
            {
                return this.CurrentRepository.Entities.FirstOrDefault(p => p.Isdeleted == "0" && p.Username == username) != null;
            }
            else
            {
                return this.CurrentRepository.Entities.FirstOrDefault(p => p.Id != id && p.Isdeleted == "0" && p.Username == username) != null;
            }
        }

        #endregion

        #region PhoneExist

        public S_user PhoneExist(string username)
        {
            return this.CurrentRepository.Entities.FirstOrDefault(p => p.Isdeleted == "0" && p.Username == username);
        }

        #endregion

        #region 根据用户名查询姓名

        /// <summary>
        /// 根据用户名查询姓名
        /// </summary>
        /// <param name="menuid"></param>
        /// <returns></returns>
        public string GetUserRealname(string username)
        {
            S_user item = this.CurrentRepository.Entities.FirstOrDefault(p => p.Username == username && p.Isdeleted == "0");
            if (item == null)
            {
                return string.Empty;
            }
            else
            {
                return item.Realname;
            }
        }

        /// <summary>
        /// 根据用户ID查询姓名
        /// </summary>
        /// <param name="userid"></param>
        /// <returns></returns>
        public string GetUserRealname(int? userid)
        {
            if (!userid.HasValue) return string.Empty;

            S_user item = this.CurrentRepository.Entities.FirstOrDefault(p => p.Id == userid.Value);
            if (item == null)
            {
                return string.Empty;
            }
            else
            {
                return item.Realname;
            }
        }

        #endregion

        #region 根据用户ID查找用户名
        public string FindNameById(int id)
        {
            var user = this.Find(id);

            return user != null ? user.Realname : "";
        }
        #endregion

        #region PageList

        public List<S_user> PageList(int pageindex, int pagesize, string roleid, string searchkey, string sort, string order, out int rowscount)
        {
            var T = this.CurrentRepository.Entities.Where(p => p.Isdeleted == "0");

            //排除开发者账号
            T = T.Where(p => p.Username != "dev" && p.Username != "manage");

            //根据属性名实现动态排序
            if (string.IsNullOrEmpty(sort)) sort = "Id";
            T = base.SortList(T, sort, order == "asc" ? true : false);

            //查询条件
            if (!string.IsNullOrEmpty(searchkey))
            {
                T = T.Where(p => p.Username.Contains(searchkey) || p.Realname.Contains(searchkey));
            }
            if (!string.IsNullOrEmpty(roleid))
            {
                var userroleids = new S_user_roleService().GetUserIdsByRoleid(roleid);

                T = T.Where(p => userroleids.Contains(p.Id));
            }

            //返回记录数
            rowscount = T.Count();
            //返回分页结果
            return this.CurrentRepository.PageList(T, pageindex, pagesize).ToList();
        }

        #endregion

        #region Save

        public bool Save(S_user item, List<UserRoleModel> userroles)
        {
            if (item.Id == 0)
            {
                item.Isdeleted = "0";
                item.Islocked = "0";
                item.Password = Utils.MD5Password(item.Password);
                this.CurrentRepository.Add(item);

                //保存用户角色
                foreach (UserRoleModel role in userroles)
                {
                    if (role.Ischecked)
                    {
                        var userrole = new S_user_role
                        {
                            User_id = item.Id,
                            Roleid = role.Roleid
                        };
                        userRoleRepository.Add(userrole);
                    }
                }
            }
            else
            {
                this.CurrentRepository.Update(item);

                //保存用户角色
                foreach (UserRoleModel role in userroles)
                {
                    S_user_role userrole = userRoleRepository.Entities.FirstOrDefault(p => p.User_id == item.Id && p.Roleid == role.Roleid);

                    if (role.Ischecked)
                    {
                        if (userrole == null)
                        {
                            userrole = new S_user_role
                            {
                                User_id = item.Id,
                                Roleid = role.Roleid
                            };

                            userRoleRepository.Add(userrole);
                        }
                    }
                    else
                    {
                        if (userrole != null)
                        {
                            userRoleRepository.Delete(userrole);
                        }
                    }
                }
            }

            return true;
        }

        #endregion

        #region CacheList

        /// <summary>
        /// 从缓存获取所有S_dict
        /// </summary>
        /// <returns></returns>
        public List<S_user> CacheList()
        {
            var cachekey = "S_user";

            var result = new MemoryCacheManager().Get<List<S_user>>(cachekey, 60, () =>
            {
                return this.CurrentRepository.Entities
                    .OrderBy(p => p.Username)
                    .ToList();
            });

            return result;
        }

        /// <summary>
        /// 更新数据后，刷新缓存
        /// </summary>
        public void RefreshCache()
        {
            var cachekey = "S_user";

            var list = this.CurrentRepository.Entities
                    .OrderBy(p => p.Username)
                    .ToList();

            new MemoryCacheManager().Remove(cachekey);
            new MemoryCacheManager().Set(cachekey, list, 60);
        }

        #endregion

        #region GetSelectList

        public SelectList GetSelectList(string roleid, string selectedValue = "")
        {

            var userroleids = new S_user_roleService().GetUserIdsByRoleid(roleid);

            var T = this.CurrentRepository.Entities.Where(p => userroleids.Contains(p.Id));

            var list = T.OrderBy(p => p.Realname).Select(p => new
            {
                value = p.Id,
                text = p.Realname
            }).ToList();

            return new SelectList(list, "value", "text", selectedValue);
        }

        #endregion

        #region ApiLogin

        private static Dictionary<string, int> loginErrorCache = new Dictionary<string, int>();

        public S_user ApiLogin(string username, string password, out string errmsg)
        {
            errmsg = "";

            var logservice = new S_user_logService();
            var user = this.FindByUsername(username);

            if (user == null)
            {
                //记录登录日志
                logservice.addUserLog(enmOprtType.登陆失败, 0, username, "用户名不存在！");

                errmsg = "用户名不存在！";
                return null;
            }
            else if (user.Islocked != "0")
            {
                //记录登录日志
                logservice.addUserLog(enmOprtType.登陆失败, 0, username, "您的账户已停用！");

                errmsg = "您的账户已停用！";
                return null;
            }
            else if (!Utils.MD5Password(password).Equals(user.Password, StringComparison.OrdinalIgnoreCase))
            {
                //记录登录日志
                logservice.addUserLog(enmOprtType.登陆失败, 0, username, "用户名或密码错误！");

                errmsg = "用户名或密码错误！";
                return null;
            }

            //记录成功日志
            logservice.addUserLog(enmOprtType.登陆成功, user.Id, user.Username, "");

            //保存上次登录时间
            user.Lastlogintime = DateTime.Now;
            user.Lastloginip = Utils.GetClientIP();
            user.Logintimes = user.Logintimes + 1;
            user.Clientid = Guid.NewGuid().ToString().Replace("-", "");
            this.CurrentRepository.Save();

            return user;
        }

        //public UserLoginResults Relogin(int userid)
        //{
        //    var user = this.Find(userid);

        //    //保存上次登录时间
        //    user.Lastlogintime = DateTime.Now;
        //    user.Lastloginip = Utils.GetClientIP();
        //    user.Logintimes = user.Logintimes;
        //    user.Clientid = Guid.NewGuid().ToString().Replace("-", "");
        //    this.CurrentRepository.Save();

        //    //保存Session
        //    var usergroup = new TB_UserGroupService().Find(user.Dept_id);
        //    SessionManage.User = new SessionUserModel(user);
        //    SessionManage.User.Groupname = usergroup == null ? "" : usergroup.GroupName;
        //    SessionManage.User.Isrepairgroup = usergroup == null ? 0 : (int)usergroup.BRepairGroup;
        //    SessionManage.ClientID = user.Clientid;
        //    //SessionManage.GlobalCustcode = user.Custcode;

        //    //用户角色
        //    var userroles = new S_user_roleRepository().Entities.Where(p => p.User_id == userid).Select(p => p.Roleid).ToList();
        //    SessionManage.UserRoles = userroles;

        //    //缓存处理
        //    UserCache.InitUsreCache(SessionManage.User);
        //    //if (UserAuthBLL.HasAuth("Study.Setting"))
        //    //{
        //    //    UserStudyCache.InitStudyCacheByCustcode(user.Custcode);
        //    //}
        //    //else
        //    //{
        //    //    UserStudyCache.InitUserStudyCache(user.Id);
        //    //}

        //    new S_user_logService().userLog(enmOprtType.重新登录, user.Id, user.Username);

        //    return UserLoginResults.Successful;
        //}

        #endregion

        //#region Logout

        //public void DoLogout()
        //{
        //    try
        //    {
        //        //记录登出日志
        //        new S_user_logService().userLog(enmOprtType.登出);

        //        //清除用户缓存
        //        UserCache.ClearUserCache(SessionManage.User);
        //        //UserStudyCache.ClearUserStudyCache(SessionManage.User.Id);

        //        //清除登录信息
        //        FormsAuthentication.SignOut();
        //        SessionManage.User = null;
        //        SessionManage.ClientID = null;
        //        SessionManage.UserRoles = null;
        //        //SessionManage.GlobalCustcode = null;
        //    }
        //    catch (Exception ex)
        //    {
        //        Log.Error(ex);
        //    }
        //}

        //#endregion

        #region 验证重复登录

        /// <summary>
        /// 验证重复登录
        /// </summary>
        /// <param name="userid"></param>
        /// <param name="session_clientid"></param>
        /// <returns>账户在其它地方登录时，返回False</returns>
        public bool CheckUserClientID(int userid, string session_clientid)
        {
            var clientid = this.CurrentRepository.Entities.Where(p => p.Id == userid).Select(p => p.Clientid).FirstOrDefault();
            if (string.IsNullOrEmpty(clientid))
            {
                return false;
            }
            else
            {
                return clientid.Equals(session_clientid);
            }
        }

        #endregion

        #region Islocked
        public void Islocked(UserLoginModel loginModel)
        {
            S_user user = FindByUsername(loginModel.Username);
            if (user != null)
            {
                user.Islocked = "1";
                this.CurrentRepository.Update(user);
            }
        }
        #endregion

        #region 获取用户菜单
        ///// <summary>
        ///// 获取用户菜单权限
        ///// </summary>
        ///// <param name="user"></param>
        //public IList<UserMenuModel> GetUsermenus(S_user user)
        //{
        //    string key = string.Format(USERMENU_ALL_KEY, user.Id);

        //    var result = new MemoryCacheManager().Get<IList<UserMenuModel>>(key, () =>
        //    {
        //        IList<S_menu> allMenuList = null;
        //        IList<UserMenuModel> userMenuList = new List<UserMenuModel>();
        //        //超级管理员
        //        if (IsSuperAdmin(user))
        //        {
        //            S_menuService sysmenuService = new S_menuService();
        //            allMenuList = sysmenuService.GetAllMenus();
        //        }
        //        else
        //        {
        //            allMenuList = GetUsermenusByUserid(user.Id);
        //        }

        //        foreach (var item in allMenuList)
        //        {
        //            var menu = new UserMenuModel
        //            {
        //                Menuid = item.Menuid,
        //                Menuname = item.Menuname_zho,
        //                Menuurl = item.Menuurl,
        //                Menuicon = item.Menuiconmiddle,
        //                ChildMenus = new List<UserMenuModel>()
        //            };
        //            if (string.IsNullOrEmpty(item.Pmenuid))
        //            {
        //                userMenuList.Add(menu);
        //            }
        //            else
        //            {
        //                var parentMenu = userMenuList.FirstOrDefault(x => x.Menuid == item.Pmenuid);
        //                if (parentMenu == null) continue;
        //                parentMenu.ChildMenus.Add(menu);
        //            }
        //        }

        //        for (var i = userMenuList.Count - 1; i >= 0; i--)
        //        {
        //            var item = userMenuList[i];
        //            if (item.ChildMenus.Count == 0) userMenuList.RemoveAt(i);
        //        }

        //        return userMenuList;
        //    });

        //    return result;
        //}

        public IList<S_menu> GetUsermenusByUserid(int userid)
        {
            var userEntity = new S_userRepository().Entities;
            var roleEntity = new S_roleRepository().Entities;
            var userRoleEntity = new S_user_roleRepository().Entities;
            var roleMenuEntity = new S_role_menuRepository().Entities;
            var menuEntity = new S_menuRepository().Entities;

            //string pamra1 = enmMenuKind.模块.ToString("d");
            //string pamra2 = enmMenuKind.菜单.ToString("d");

            var result = (from u in userEntity
                          join ur in userRoleEntity on u.Id equals ur.User_id
                          join rm in roleMenuEntity on ur.Roleid equals rm.Roleid
                          join m in menuEntity on rm.Menuid equals m.Menuid
                          where u.Id == userid && m.Status != (int)enmMenuStatus.Locked
                          orderby m.Orderseq
                          select m
                )
                //Distinct报错，提示不识别这个条件，无法生成sql
                //.Distinct(new MenuCompare())
                .GroupBy(g => g.Id)
                .Select(x => x.FirstOrDefault())
                .OrderBy(p => p.Orderseq)
                .ToList<S_menu>();

            return result;
        }

        ///// <summary>
        ///// 获取用户权限
        ///// </summary>
        ///// <param name="user"></param>
        //public IList<Auth.Auth> GetUserAuths(S_user user)
        //{
        //    string key = string.Format(USERAUTH_ALL_KEY, user.Id);

        //    var result = new MemoryCacheManager().Get<IList<Auth.Auth>>(key, () =>
        //    {
        //        IList<S_menu> allMenuList = null;
        //        IList<Auth.Auth> allUserAuthList = new List<Auth.Auth>();
        //        //超级管理员
        //        if (IsSuperAdmin(user))
        //        {
        //            S_menuService sysmenuService = new S_menuService();
        //            allMenuList = (from m in new S_menuRepository().Entities
        //                           orderby m.Orderseq
        //                           select m).ToList();
        //        }
        //        else
        //        {
        //            allMenuList = GetUserAuthByUserid(user.Id);
        //        }

        //        foreach (var item in allMenuList)
        //        {
        //            allUserAuthList.Add(new Auth.Auth
        //            {
        //                Authcode = item.Menuid,
        //                Authname = item.Menuname_zho
        //            });
        //        }
        //        return allUserAuthList;
        //    });

        //    return result;
        //}

        //public IList<S_menu> GetUserAuthByUserid(int userid)
        //{
        //    var userEntity = new S_userRepository().Entities;
        //    var roleEntity = new S_roleRepository().Entities;
        //    var userRoleEntity = new S_user_roleRepository().Entities;
        //    var roleMenuEntity = new S_role_menuRepository().Entities;
        //    var menuEntity = new S_menuRepository().Entities;

        //    var result = (from u in userEntity
        //                  join ur in userRoleEntity on u.Id equals ur.User_id
        //                  join rm in roleMenuEntity on ur.Roleid equals rm.Roleid
        //                  join m in menuEntity on rm.Menuid equals m.Menuid
        //                  where u.Id == userid && m.Status != (int)enmMenuStatus.Locked
        //                  orderby m.Orderseq
        //                  select m
        //        )
        //        //Distinct报错，提示不识别这个条件，无法生成sql
        //        //.Distinct(new MenuCompare())
        //        .GroupBy(g=>g.Id)
        //        .Select(x=>x.FirstOrDefault())
        //        .ToList<S_menu>();

        //    return result;
        //}

        #endregion

        #region 删除

        public bool DeleteByIds(string ids)
        {
            foreach (string id in ids.Split(','))
            {
                if (string.IsNullOrEmpty(id)) continue;

                //逻辑删除
                var item = this.CurrentRepository.Find(Convert.ToInt32(id));
                item.Isdeleted = "1";
                this.CurrentRepository.Update(item, false);
            }

            this.CurrentRepository.Save();

            return true;
        }

        public bool DeleteUser(S_user user)
        {
            user.Isdeleted = "1";
            this.CurrentRepository.Update(user);

            return true;
        }

        #endregion

        #region 更新密码

        public bool updatePwd(S_user user, string pwd)
        {
            if (user != null)
            {
                this.CurrentRepository.Update(user, true);
            }
            return true;
        }


        #endregion

        #region 根据clientid查找用户集合
        public List<S_user> getUserModel(string clientid)
        {
            return this.CurrentRepository.Entities.Where(p => p.Clientid == clientid).ToList();
        }
        #endregion
    }

    public class MenuCompare : IEqualityComparer<S_menu>
    {

        public bool Equals(S_menu x, S_menu y)
        {
            //Check whether the compared objects reference the same data.
            if (Object.ReferenceEquals(x, y)) return true;

            //Check whether any of the compared objects is null.
            if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
                return false;

            return x.Id == y.Id;
        }

        public int GetHashCode(S_menu obj)
        {
            //Check whether the object is null
            if (Object.ReferenceEquals(obj, null)) return 0;

            return obj.Id.GetHashCode();
        }



    }

}
